package com.zrq.gencode.jdbc;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.zrq.gencode.domain.tabledata.ColumnBase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author zhong
 * @date  2020年1月8日
 */
public class DataTable {
	private static final Logger LOGGER = LoggerFactory.getLogger(DataTable.class);

    private static final String SQL = "SELECT * FROM ";

    /**
     * 获取当前表名
     *
     * @return List<String>
     */
    public static List<String> getTableNames() {
        List<String> tableNames = new ArrayList<>();
        Connection conn = null;
        ResultSet rs = null;
        try {
            conn = ConnectionPool.getConnection();
            // 检查连接是否成功建立

	        LOGGER.debug("数据库连接成功建立");

            DatabaseMetaData db = conn.getMetaData();
            // 尝试获取当前目录和模式
            String catalog = conn.getCatalog();
            String schema = conn.getSchema();

            LOGGER.debug("Catalog: {}", catalog);
            LOGGER.debug("Schema: {}", schema);

            // 先尝试使用null作为schemaPattern
            rs = db.getTables(catalog, null, null, new String[]{"TABLE"});

            // 检查是否获取到结果
            if (!rs.isBeforeFirst() && !rs.next()) {
                LOGGER.debug("在catalog={}, schema=null的情况下未找到表", catalog);
                // 如果没有获取到表，尝试使用schema作为schemaPattern
                rs.close();
                rs = db.getTables(catalog, schema, null, new String[]{"TABLE"});
                if (!rs.isBeforeFirst() && !rs.next()) {
                    LOGGER.debug("在catalog={}, schema={}的情况下未找到表", catalog, schema);
                    // 如果还是没有获取到表，尝试不指定catalog
                    rs.close();
                    rs = db.getTables(null, null, null, new String[]{"TABLE"});
                    if (!rs.isBeforeFirst() && !rs.next()) {
                        LOGGER.debug("在catalog=null, schema=null的情况下未找到表");
                    }
                }
            }

            // 重新定位到第一行
            rs.beforeFirst();

            int count = 0;
            while (rs.next()) {
                String tableName = rs.getString(3);
                tableNames.add(tableName);
                LOGGER.debug("发现表: {}", tableName);
                count++;
            }

            LOGGER.info("总共找到 {} 个表", count);
        } catch (SQLException e) {
            LOGGER.error("获取表名时发生错误", e);
        } finally {
            try {
                if (rs != null) {
                    rs.close();
                }
                // 连接池中的连接会在close时自动返回池中，不需要特殊处理
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                LOGGER.error("关闭数据库资源时发生错误", e);
            }
        }
        return tableNames;
    }

    /**
     * 获取表中所有字段信息
     *
     * @return List<ColumnBase>
     */
    @SuppressWarnings("SqlSourceToSinkFlow")
    public static List<ColumnBase> getColumns(String tableName) {
        List<ColumnBase> columns = new ArrayList<>();
	    try (Connection conn = ConnectionPool.getConnection()) {
		    // 检查连接是否成功建立

		    LOGGER.debug("正在获取表 {} 的字段信息", tableName);

		    String tableSql = SQL + tableName;
		    try (PreparedStatement pStemt = conn.prepareStatement(tableSql)) {
			    ResultSetMetaData rsmd = pStemt.getMetaData();
			    int size = rsmd.getColumnCount();
			    LOGGER.debug("表 {} 有 {} 个字段", tableName, size);
			    for (int i = 0; i < size; i++) {
				    ColumnBase columnBase = new ColumnBase();
				    columnBase.setSqlType(rsmd.getColumnTypeName(i + 1).split("\\s+")[0]);
				    columnBase.setName(rsmd.getColumnName(i + 1));
				    columns.add(columnBase);
				    LOGGER.debug("字段 {}: {} ({})", (i + 1), columnBase.getName(), columnBase.getSqlType());
			    }
		    }
	    } catch (SQLException e) {
		    LOGGER.error("获取表 {} 字段信息时发生错误", tableName, e);
	    }
	    // 连接池中的连接会在close时自动返回池中，不需要特殊处理
	    return columns;
    }
}